layui.define(['ztree', 'tool', 'geneconfig'], function(exports) {
    var $ = layui.jquery,
        _geneconfig_ = layui.geneconfig,
        _body_ = $('body'),
        _tool_ = layui.tool;

    layui.link(_geneconfig_.getModulePath() + '/css/treeselect.css');
    var TreeSelect = function(options) {
        this.__render(options);
    };
    /**
     * 用于捕获单击节点之前的事件回调函数，并且根据返回值确定是否允许单击操作，这里处理checkbox选中
     */
    function beforeClick(treeId, treeNode) {
        var zTree = $.fn.zTree.getZTreeObj(treeId);
        zTree && zTree.checkNode(treeNode, !treeNode.checked, null, true);
        return false;
    }
    /**
     *用于捕获 勾选 或 取消勾选 之前的事件回调函数，并且根据返回值确定是否允许 勾选或取消勾选，这里处理是否允许多选
     */
    function beforeCheck(treeId, treeNode) {
        var zTree = $.fn.zTree.getZTreeObj(treeId);
        //不是多选模式
        if(zTree && zTree.setting && zTree.setting.view && !zTree.setting.view.selectedMulti) {
            zTree.checkAllNodes(false);
        }
        if(zTree && !zTree._parentCheck && treeNode.isParent) {
            return false;
        }
    }
    //点击事件的处理
    function onCheck(e, treeId, treeNode) {
        var zTree = $.fn.zTree.getZTreeObj(treeId);
        if(!!!zTree) {
            return;
        }
        var nodes = zTree.getCheckedNodes(true), //获取选中的节点
            len = nodes.length,
            valIds = [],
            _htm = [];;
        for(var i = 0; i < len; i++) {
            valIds.push(nodes[i].id);
            _htm.push('<a href="javascript:;">');
            _htm.push(nodes[i].name);
            _htm.push(' <i class="layui-icon" data-action="close" data-tid="');
            _htm.push(nodes[i].tId);
            _htm.push('" data-id="');
            _htm.push(nodes[i].id);
            _htm.push('">&#x1006;</i></a>');
        }
        zTree._treeInput.html(_htm.join(''));
        zTree._target.val(valIds.join(zTree._separator));
    }
    TreeSelect.fn = TreeSelect.prototype;
    /**
     * 渲染treeSelect
     */
    TreeSelect.fn.__render = function(options) {
        if(this._initialized) {
            layui.hint().error('TreeSelect已经初始化！');
            return;
        }
        options = options || {};
        if(!!options.elem) {
            this._container = $(options.elem);
            //存在配置的容器
            if(!this._container.length) {
                this._container = undefined;
            }
        }
        if(!this._container) {
            //选取默认容器
            this._container = _body_.find('input[gene-treeselect]');
        }
        if(!this._container || !this._container.length) {
            layui.hint().error('TreeSelect没有正常初始化！');
            return;
        }
        this._container = this._container.eq(0);

        var _that = this,
            _elem = this._container,
            _parent = _elem.parent(),
            _treeInput = $('<div class="ztree-input"></div>'),
            _treeInputId = _tool_.makeHashCode('treeInput'),
            _treeContent = $('<div class="ztree-content layui-anim layui-anim-upbit"></div>'),
            _treeContentId = _tool_.makeHashCode('treeContent'),
            _tree = $('<ul class="ztree"></ul>'),
            _treeId = _tool_.makeHashCode('tree'),
            _separator = options.separator || ',',
            _parentCheck = !!options.parentCheck;
        _parent.addClass("gene-treeselect").find('.ztree-input,.ztree-content').remove();
        _treeInput.attr("id", _treeInputId);
        _treeContent.attr("id", _treeContentId);
        _tree.attr("id", _treeId);
        _treeContent.append(_tree);
        _parent.append(_treeInput).append(_treeContent);
        _that.__treeId = _treeId;

        // 设置可参考ztree.js配置 URL:http://www.treejs.cn/v3/api.php
        var setting = {
            check: {
                enable: true,
                chkboxType: {
                    "Y": "",
                    "N": ""
                }
            },
            view: {
                expandSpeed: 'normal',
                dblClickExpand: false
            },
            data: {
                simpleData: {
                    enable: true
                }
            },
            callback: {
                beforeClick: beforeClick,
                beforeCheck: beforeCheck,
                onCheck: onCheck
            }
        };

        if(options.async) setting.async = options.async;

        if(options.data) {
            var _data = options.data;
            if(_data.key) setting.data.key = _data.key;
            if(_data.simpleData) setting.data.simpleData = _data.simpleData;
        }

        if(options.view) {
            var _view = options.view;
            if(_view.expandSpeed) setting.view.expandSpeed = _view.expandSpeed;
            if(_view.fontCss) setting.view.fontCss = _view.fontCss;
            if(_view.nameIsHTML) setting.view.nameIsHTML = _view.nameIsHTML;
            if(_view.selectedMulti) setting.view.selectedMulti = _view.selectedMulti;
            if(_view.showIcon) setting.view.showIcon = _view.showIcon;
            if(_view.showLine) setting.view.showLine = _view.showLine;
            if(_view.showTitle) setting.view.showTitle = _view.showTitle;
        }

        if(options.callback) {
            var _callback = options.callback;
            if(typeof _callback.beforeCheck == 'function') {
                setting.callback.beforeCheck = function(treeId, treeNode) {
                    if(_callback.beforeCheck(treeId, treeNode) === false) {
                        return false;
                    }
                    return beforeCheck(treeId, treeNode);
                };
            }
            if(_callback.beforeAsync) setting.callback.beforeAsync = _callback.beforeAsync;
            if(_callback.onAsyncError) setting.callback.onAsyncError = _callback.onAsyncError;
            if(_callback.onAsyncSuccess) setting.callback.onAsyncSuccess = _callback.onAsyncSuccess;
        }

        // 初始化zTree
        var zTree = $.fn.zTree.init(_tree, setting, options.treeData);
        zTree._target = _elem;
        zTree._treeInput = _treeInput;
        zTree._separator = _separator;
        zTree._parentCheck = _parentCheck;
        // 获取所有节点
        var _nodes = zTree.getNodes();
        // 获取初始值
        var _vals = _elem.val();
        if(!!$.trim(_vals).length) {
            _initNode(_nodes, _vals.split(_separator), zTree);
        }

        // input 框点击事件
        _treeInput.off('click').on('click', function() {
            _treeContent.show();
        });
        $(document).off('mousedown').on("mousedown", function(event) {
            if(!(event.target.id == _treeInputId || event.target.id == _treeContentId || !!$(event.target).parents('#' + _treeContentId).length)) {
                // 隐藏ztree
                _treeContent.fadeOut('fast');
            }
        });
        _bindCloseEvent(_treeInput, _elem, zTree);
        _that._initialized = true;
        return _that;
    };

    TreeSelect.fn.render = function() {
        if(!this._initialized) {
            return;
        }
        var zTree = $.fn.zTree.getZTreeObj(this.__treeId);
        if(!!!zTree) {
            return;
        }
        zTree.checkAllNodes(false);
        // 获取所有节点
        var _nodes = zTree.getNodes();
        // 获取初始值
        var _vals = zTree._target.val();
        zTree._treeInput.empty();
        if(!!$.trim(_vals).length) {
            _initNode(_nodes, _vals.split(zTree._separator), zTree);
        }
    }

    /**
     * @param {Object} nodes 节点
     * @param {Object} vals 值数组
     */
    function _initNode(nodes, vals, zTree) {
        for(var i = 0, l = nodes.length; i < l; i++) {
            var node = nodes[i];
            if(_findArray(vals, node.id) !== -1) {
                zTree.checkNode(node, true, false);
                zTree._treeInput.append([
                    '<a href="javascript:;">',
                    node.name,
                    ' <i class="layui-icon" data-action="close" data-tid="' + node.tId + '" data-id="' + node.id + '">&#x1006;</i>',
                    '</a>'
                ].join(''));
            }
            if(!!node.children && !!node.children.length) {
                // 递归调用
                _initNode(node.children, vals, zTree);
            }
        }
    };
    /**
     * 绑定删除按钮事件
     * @param {Object} elem 输入框（实际是DIV）
     * @param {Object} target 关联的原输入框
     */
    function _bindCloseEvent(elem, target, zTree) {
        elem.on('click', 'i[data-action=close]', function(e) {
            layui.stope(e);
            var $this = $(this);
            // 获取id
            var id = $this.data('id');
            // 获取tid
            var tid = $this.data('tid');
            // 处理节点显示
            var node = zTree.getNodeByTId(tid);
            // 将对应的ztree节点的check取消选中
            zTree.checkNode(node, false, false);
            // 处理input 值
            var inputs = target.val().split(zTree._separator);
            // 移除当前所选值Id
            _remove(inputs, id);
            // 重新辅助
            target.val(inputs.join(zTree._separator));
            // 移除截元素
            $this.parent().remove();
        });
    };

    function _indexOf(arr, val) {
        for(var i = 0; i < arr.length; i++) {
            if(arr[i] == val) return i;
        }
        return -1;
    };

    function _remove(arr, val) {
        var index = _indexOf(arr, val);
        if(index > -1) {
            arr.splice(index, 1);
        }
    };
    /**
     *
     * 查找数组，返回匹配到的第一个index
     *
     * @param array 被查找的数组
     * @param feature 查找特征 或者为一个具体值，用于匹配数组遍历的值，或者为一个对象，表明所有希望被匹配的key-value
     * @param or boolean 希望命中feature全部特征或者只需命中一个特征，默认true
     *
     * @return 数组下标  查找不到返回-1
     */
    function _findArray(array, feature, all) {
        all = all || true;
        for(var index in array) {
            var cur = array[index];
            if(feature instanceof Object) {
                var allRight = true;
                for(var key in feature) {
                    var value = feature[key];
                    if(cur[key] == value && !all) return index;
                    if(all && cur[key] != value) {
                        allRight = false;
                        break;
                    }
                }
                if(allRight) return index;
            } else {
                if(cur == feature) {
                    return index;
                }
            }
        }
        return -1;
    };

    function TreeSelectExport() {}
    TreeSelectExport.prototype.render = function(options) {
        return new TreeSelect(options);
    };
    exports("treeselect", new TreeSelectExport());
});